<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<input type="text" id="inputValue"/>
<button id="btn">打开/创建database</button>
<br>
<button id="nextBtn">正序索引游标获取所有</button>
<br>


<script>
  // 我们的客户数据看起来像这样。
  const customerData = [
    {ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com"},
    {ssn: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org"},
    {ssn: "666-66-6666", name: "Tony", age: 23, email: "ony@home.org"},
    {ssn: "888-88-8888", name: "Donna", age: 27, email: "donna2@home.org"},
    {ssn: "999-99-9999", name: "Yoga", age: 18, email: "yoga@home.org"}
  ];
  let db = null
  const openDatabase = function (version) {
    console.log('database version:', version)
    // 如果数据库不存在，open 操作会创建该数据库,第二个参数指定数据库的版本
    const request = window.indexedDB.open('MySecondDatabase', version)

    request.onsuccess = function (event) {
      db = event.target.result
      console.log('database success')
      noteDatabase(db)
    }

    request.onerror = function (event) {
      console.log('database fail:', event.target.error.message)
    }

    // 当你创建一个新的数据库或者增加已存在的数据库的版本号（当打开数据库时，指定一个比之前更大的版本号）， onupgradeneeded 事件会被触发
    request.onupgradeneeded = function (event) {
      console.log('database onupgradeneeded')

      // 保存 IDBDataBase 接口
      db = event.target.result

      try {
        db.deleteObjectStore('customers')
      } catch (e) {
      }
      const objectStore = db.createObjectStore('customers', {keyPath: 'ssn'})

      // 建立一个索引来通过姓名来搜索客户。名字可能会重复，所以我们不能使用 unique 索引
      objectStore.createIndex("name", "name", {unique: false});
      // email不允许重复
      objectStore.createIndex('email', 'email', {unique: true})

      // 使用事务的 oncomplete 事件确保在插入数据前对象仓库已经创建完毕
      objectStore.transaction.oncomplete = function () {
        const transaction = db.transaction('customers', 'readwrite')
        const customersObjectStore = transaction.objectStore('customers')
        customerData.forEach(item => {
          customersObjectStore.add(item)
        })
      }

      noteDatabase(db)
    }

    // 如果其他的一些页签加载了该数据库，在我们继续之前需要关闭它们
    // 但如果我们正确处理了 onversionchange 事件后，这个事件就不会被触发了
    // 因为这表示：还有另一个指向同一数据库的连接并且在 db.onversionchange 被触发后，依然保持着连接
    request.onblocked = function () {
      alert("请关闭其他由该站点打开的页签！");
    }
  }

  /**
   * 当你的网页应用以数据库版本变更的方式发生改变时，
   * 你需要考虑，如果用户在一个标签页中打开的应用里使用了旧版本的数据库，在另一个标签页里加载新版本的数据库时会发生什么。
   * 当你使用更高的版本号调用 open() 方法时，其他所有打开的数据库必须显式地确认请求，
   * 你才能对数据库进行修改（onblocked 事件会被触发知道它们被关闭或重新加载）
   * @param db
   */

  function noteDatabase(db) {
    // 当由其他页签请求了版本变更时，会添加一个会被通知的事件处理程序。
    // 如果我们不监听 versionchange 事件，也不去关闭旧连接，那么新的连接就不会建立。openRequest 对象会产生 blocked 事件，而不是 success 事件。因此另一个标签页无法正常工作。
    db.onversionchange = function (event) {
      // 我们需要监听这个事件，关闭对旧版本数据库的连接（还应该建议访问者重新加载页面，以加载最新的代码）。
      db.close();
      alert("数据库版本被更新，请确认后重新加载当前页签");
    };
    db.onerror = function (event) {
      alert('访问数据库错误：' + event.target.error.message);
    };
    // 处理数据库
  }

  const getData = (keyRang = null, direction = 'next') => {
    const index = db
      .transaction('customers')
      .objectStore('customers')
      .index('name')
    const data = []
    index.openCursor(keyRang, direction).onsuccess = function (event) {
      const cursor = event.target.result
      if (cursor) {
        // cursor.key 是一个 name, 就像 "Bill", 然后 cursor.value 是整个对象。
        data.push(cursor.value)
        cursor.continue()
      } else {
        console.log('get data:')
        console.log(data)
      }
    }
  }

  nextBtn.addEventListener('click', () => {
    getData()
  })

  btn.addEventListener('click', () => {
    openDatabase(Number(inputValue.value || 1))
  })
</script>
</body>
</html>
